package pl.edu.pw.elka.jtrzasko.proz.warcaby.controller;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;

import pl.edu.pw.elka.jtrzasko.proz.warcaby.figures.FigureColor;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.client.ClientMessage;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.messages.server.ServerMessage;
import pl.edu.pw.elka.jtrzasko.proz.warcaby.view.ServerView;

/**
 * Klasa zawiera serwer odpowiedzialny z komunikacje kontrolera z klientami
 * 
 */
public class Server implements Runnable
{
	/**
	 * Port na ktorym nasluchuje serwer
	 */
	private int port;
	/**
	 * Gniazdo przydzielone do serwera
	 */
	private ServerSocket serverSocket;
	/**
	 * Kolejka do wstawiania odebranych komunikatow od klienta
	 */
	private LinkedBlockingQueue<ClientMessage> queue;
	/**
	 * Strumien do wysylania informacji do pierwszego klienta
	 */
	private ObjectOutputStream out1;
	/**
	 * Strumien do wysylania informacji do drugiego klienta
	 */
	private ObjectOutputStream out2;

	/**
	 * Utworzenie nowego serwera glownego nasluchujacego na konkrentym porcie
	 * 
	 * @param port
	 *            Port nasluchu
	 * 
	 */
	public Server(Integer port)
	{
		this.port = port;
		ServerController controller = new ServerController(this);
		queue = controller.getQueue();
		new Thread(controller).start();
	}

	public void run()
	{
		try
		{
			serverSocket = new ServerSocket(port);
			while (true)
			{
				Socket clientSocket = serverSocket.accept();
				try
				{
					new Thread(new ServerThread(clientSocket, queue, this))
							.start();
				} catch (IOException e)
				{
					clientSocket.close();
				}
			}

		} catch (IOException e)
		{
			System.out.println("Main Server start error");
		}

		finally
		{
			try
			{
				System.out.println("Collecting clients complited");
				serverSocket.close();
			} catch (IOException e)
			{
				System.out.println("Can't stop main Server");
			}
		}
	}

	/**
	 * Dodanie nowego strumienia wyjsciowego dla konkretnego klienta, do ktorego
	 * beda zapisywane informacje wysylane do klienta
	 * @param out Strumien wyjsciowy do wysylania informacji do klieta
	 */
	public void addClientOutStream(ObjectOutputStream out) throws IOException
	{
		if (out1 == null)
		{
			out1 = out;
			System.out.println("Added Client 1");
		} else if (out2 == null)
		{
			System.out.println("Added Client 2");
			out2 = out;
		}

	}

	/**
	 * Wysyla komunikat do klienta
	 * @param playerColor Kolor gracza, do ktorego ma byc wyslany komunikat
	 * @param clientAction Rodzaj komunikatu jaki ma zostac wyslany
	 */
	public void sendActionToClients(FigureColor playerColor,
			ServerMessage clientAction)
	{
		try
		{
			if (out1 != null && playerColor == FigureColor.WHITE)
			{
				out1.writeObject(clientAction);
				out1.flush();
				out1.reset();
			}
			if (out2 != null && playerColor == FigureColor.BLACK)
			{
				out2.writeObject(clientAction);
				out2.flush();
				out2.reset();
			}
		} catch (Exception e)
		{
			System.out.println("Error during sending ActionToClients");
		}

	}

	/**
	 * Przerwanie dzialania serwera
	 */
	public void disconnet()
	{
		try
		{
			serverSocket.close();
		} catch (IOException e)
		{
			System.out.println("Can't stop main Server");
		}

	}

}
